package com.puboot.module.blog.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.mysql.cj.util.TimeUtil;
import com.puboot.common.constants.BaseConstants;
import com.puboot.common.util.*;
import com.puboot.module.admin.model.BizArticleLook;
import com.puboot.module.admin.model.BizComment;
import com.puboot.module.admin.model.BizLove;
import com.puboot.module.admin.model.BizMessage;
import com.puboot.module.admin.service.*;
import com.puboot.module.admin.vo.CommentConditionVo;
import com.puboot.module.admin.vo.base.ResponseVo;
import com.puboot.module.blog.model.Company;
import com.puboot.module.blog.model.Customer;
import com.puboot.module.blog.service.CompanyService;
import com.puboot.module.blog.service.CustomerService;
import com.puboot.module.blog.service.SMSService;
import com.wf.captcha.utils.CaptchaUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static org.apache.shiro.crypto.hash.Sha256Hash.ALGORITHM_NAME;

/**
 * 给前台页面提供的接口，包括针对文章进行的添加评论、获取评论、增加浏览次数和点赞操作
 *
 * @author Linzhaoguan
 * @version V1.0
 * @date 2019年9月11日
 */
@Slf4j
@RestController
@RequestMapping("blog/api")
@AllArgsConstructor
public class BlogApiController {

    private final BizCommentService commentService;
    private final BizArticleLookService articleLookService;
    private final BizLoveService loveService;

    @Autowired
    private final RedisService redisService;
    private final CustomerService customerService;
    private final CompanyService companyService;
    private final HttpServletRequest httpServletRequest;

    private final BizMessageService bizMessageService;

    private final SMSService smsService;

    @PostMapping("comments")
    public IPage<BizComment> getComments(CommentConditionVo vo, Integer pageNumber, Integer pageSize) {
        return commentService.selectComments(vo, pageNumber, pageSize);
    }

    @PostMapping("comment/save")
    public ResponseVo saveComment(HttpServletRequest request, BizComment comment) throws UnsupportedEncodingException {
        if (org.springframework.util.StringUtils.isEmpty(comment.getNickname())) {
            return ResultUtil.error("请输入昵称");
        }
        String content = comment.getContent();
        if (!XssKillerUtil.isValid(content)) {
            return ResultUtil.error("内容不合法");
        }
        content = XssKillerUtil.clean(content.trim()).replaceAll("(<p><br></p>)|(<p></p>)", "");
        Date date = new Date();
        comment.setContent(content);
        comment.setIp(IpUtil.getIpAddr(request));
        comment.setCreateTime(date);
        comment.setUpdateTime(date);
        if (StringUtils.isNotBlank(comment.getQq())) {
            comment.setAvatar("http://q1.qlogo.cn/g?b=qq&nk=" + comment.getQq() + "&s=100");
        } else if (StringUtils.isNotBlank(comment.getEmail())) {
            String entry = null;
            try {
                entry = MD5.md5Hex(comment.getEmail());
            } catch (NoSuchAlgorithmException e) {
                log.error("MD5出现异常{}", e.getMessage(), e);
            }
            comment.setAvatar("http://www.gravatar.com/avatar/" + entry + "?d=mp");
        }
        boolean a = commentService.save(comment);
        if (a) {
            return ResultUtil.success("评论提交成功,系统正在审核");
        } else {
            return ResultUtil.error("评论提交失败");
        }
    }


    @PostMapping("article/look")
    public ResponseVo checkLook(HttpServletRequest request, Integer articleId) {
        /*浏览次数*/
        Date date = new Date();
        String ip = IpUtil.getIpAddr(request);
        int checkCount = articleLookService.checkArticleLook(articleId, ip, DateUtil.addHours(date, -1));
        if (checkCount == 0) {
            BizArticleLook articleLook = new BizArticleLook();
            articleLook.setArticleId(articleId);
            articleLook.setUserIp(ip);
            articleLook.setLookTime(date);
            articleLook.setCreateTime(date);
            articleLook.setUpdateTime(date);
            articleLookService.save(articleLook);
            return ResultUtil.success("浏览次数+1");
        } else {
            return ResultUtil.error("一小时内重复浏览不增加次数哦");
        }
    }


    @PostMapping("love")
    public ResponseVo love(HttpServletRequest request, Integer bizId, Integer bizType) {
        Date date = new Date();
        String ip = IpUtil.getIpAddr(request);
        BizLove bizLove = loveService.checkLove(bizId, ip);
        if (bizLove == null) {
            bizLove = new BizLove();
            bizLove.setBizId(bizId);
            bizLove.setBizType(bizType);
            bizLove.setUserIp(ip);
            bizLove.setStatus(CoreConst.STATUS_VALID);
            bizLove.setCreateTime(date);
            bizLove.setUpdateTime(date);
            loveService.save(bizLove);
            return ResultUtil.success("点赞成功");
        } else {
            return ResultUtil.error("您已赞过了哦~");
        }
    }

    @PostMapping("/sendcode")
    public ResponseVo sendCode(String phone, String code, HttpServletRequest request) {
        try {

            //判断验证码
            if (!CaptchaUtil.ver(code, request)) {
                // 清除session中的验证码
                CaptchaUtil.clear(request);
                return ResultUtil.error("验证码错误！");
            }

            //判断是否存在此用户
            Customer customer = customerService.getByUsername(phone);

            if (customer != null) {
                return ResultUtil.error("此用户已存在，请登录！");
            }

            int phoneCode = (int) ((Math.random() * 9 + 1) * 100000);
            //TODO 验证同一手机号，30分钟内只请求一次网关
            //TODO 验证同一IP地址，30分钟内只能请求5次

            //TODO 请求网关发送验证码
            smsService.sendSMS(phoneCode + "", phone);


            //发送成功后，将code 和手机号 存入缓存，待验证, 有效期5分钟
            redisService.set("phonecode:" + phone, phoneCode, 5L, TimeUnit.MINUTES);
            return ResultUtil.success("发送成功", phoneCode);
        } catch (Exception e) {
            log.error("发送失败", e);
            return ResultUtil.error("发送失败");
        }
    }

    @PostMapping("/forgetsendcode")
    public ResponseVo forgetSendCode(String phone, String code, HttpServletRequest request) {
        try {

            //判断验证码
            if (!CaptchaUtil.ver(code, request)) {
                // 清除session中的验证码
                CaptchaUtil.clear(request);
                return ResultUtil.error("验证码错误！");
            }

            //判断是否存在此用户
            Customer customer = customerService.getByUsername(phone);

            if (customer == null) {
                return ResultUtil.error("此用户不存在，请重新输入账号！");
            }

            int phoneCode = (int) ((Math.random() * 9 + 1) * 100000);
            //TODO 验证同一手机号，30分钟内只请求一次网关
            //TODO 验证同一IP地址，30分钟内只能请求5次

            //TODO 请求网关发送验证码
            smsService.sendForgetSMS(phoneCode + "", phone);

            //发送成功后，将code 和手机号 存入缓存，待验证, 有效期5分钟
            redisService.set("forgetsendcode:" + phone, phoneCode, 5L, TimeUnit.MINUTES);
            return ResultUtil.success("发送成功", phoneCode);
        } catch (Exception e) {
            log.error("发送失败", e);
            return ResultUtil.error("发送失败");
        }
    }

    @PostMapping("/regist/input")
    public ResponseVo regist(String username, String phonecode, String nicname, String password, String companyname, String deptname, String industry, String province, String city) {
        try {
            //验证手机验证码是否正确
            Integer redisCode = redisService.get("phonecode:" + username);
            if (!Objects.equals(phonecode, redisCode != null ? redisCode + "" : "")) {
                return ResultUtil.error("手机验证码不正确，请重新输入");
            }

            //判断是否存在此用户
            Customer customer = customerService.getByUsername(username);

            if (customer != null) {
                return ResultUtil.error("此用户已存在，请登录！");
            }

            if (StringUtils.isNotBlank(companyname)) {
                //保存公司信息
                Company company = companyService.getByName(companyname);
                if (company != null) {
                    return ResultUtil.error("此公司已存在，请确认！");
                }
            }
            customerService.regist(username, nicname, password, companyname, deptname, industry, province, city);
            return ResultUtil.success("注册成功");
        } catch (Exception e) {
            log.error("注册失败", e);
            return ResultUtil.error("注册失败");
        }
    }


    @PostMapping("/login/input")
    public ResponseVo login(String username, String password, String code, HttpServletRequest request, HttpSession session) {

        try {

            //判断验证码
            if (!CaptchaUtil.ver(code, request)) {
                // 清除session中的验证码
                CaptchaUtil.clear(request);
                return ResultUtil.error("验证码错误！");
            }

            //判断是否存在此用户
            Customer customer = customerService.getByUsername(username);

            if (customer == null) {
                return ResultUtil.error("手机号或密码错误");
            }

            //加密密码
            String encodePassword = new SimpleHash(ALGORITHM_NAME, password, ByteSource.Util.bytes(username), 2).toHex();

            if (!Objects.equals(customer.getPassword(), encodePassword)) {
                return ResultUtil.error("手机号或密码错误");
            }

            //登录成功，放入session
            session.setAttribute("customer", customer);

            return ResultUtil.success("登录成功");
        } catch (Exception e) {
            log.error("登录失败", e);
            return ResultUtil.error("登录失败");
        }
    }

    @PostMapping("/logout/input")
    public ResponseVo logout(HttpSession session) {
        try {
            session.setAttribute("customer", null);
            return ResultUtil.success("退出登录成功");
        } catch (Exception e) {
            log.error("退出登录失败", e);
            return ResultUtil.error("退出登录失败");
        }
    }


    @PostMapping("/changepassword/input")
    public ResponseVo changepassword(String username, String phonecode, String password) {
        try {
            //验证手机验证码是否正确
            Integer redisCode = redisService.get("forgetsendcode:" + username);
            if (!Objects.equals(phonecode, redisCode != null ? redisCode + "" : "")) {
                return ResultUtil.error("手机验证码不正确，请重新输入");
            }
            //判断是否存在此用户
            Customer customer = customerService.getByUsername(username);
            if (customer == null) {
                return ResultUtil.error("此用户不存在，请重新输入！");
            }
            customerService.changepassword(username, password);
            return ResultUtil.success("修改密码成功!");
        } catch (Exception e) {
            log.error("修改密码失败", e);
            return ResultUtil.error("修改密码失败");
        }
    }

    @PostMapping("/getVip")
    public ResponseVo getVip() {
        try {
            HttpSession httpSession = httpServletRequest.getSession();
            Customer customer = (Customer) httpSession.getAttribute("customer");
            return ResultUtil.success("获取客户数据成功!", customer);
        } catch (Exception e) {
            log.error("获取客户数据失败", e);
            return ResultUtil.error("获取客户数据失败");
        }
    }

    @PostMapping("/message/submit")
    public ResponseVo<Integer> submitMessage(String username, String phone, String email, String qq, String content, HttpServletRequest request) {
        try {

            if (username.length() > 15) {
                return ResultUtil.error("姓名长度不能大于15", Constants.STATE_INVAILD);
            }

            if (phone.length() > 15) {
                return ResultUtil.error("手机号码长度不能大于15", Constants.STATE_INVAILD);
            }

            if (email.length() > 30) {
                return ResultUtil.error("邮箱地址长度不能大于15", Constants.STATE_INVAILD);
            }

            if (qq.length() > 20) {
                return ResultUtil.error("QQ长度不能大于20", Constants.STATE_INVAILD);
            }

            if (content.length() > 500) {
                return ResultUtil.error("反馈内容字数不能大于500", Constants.STATE_INVAILD);
            }

            String ip = IpUtil.getIpAddr(request);
            String v = redisService.get("message:" + ip);

            if (StringUtils.isBlank(v)) {
                BizMessage bizMessage = new BizMessage();
                bizMessage.setContent(content);
                bizMessage.setEmail(email);
                bizMessage.setPhone(phone);
                bizMessage.setUsername(username);
                bizMessage.setQq(qq);
                bizMessage.setStatus(CoreConst.STATUS_VALID);
                bizMessage.setCreateTime(new Date());
                bizMessageService.save(bizMessage);
                redisService.set("message:" + ip, "1", 20, TimeUnit.SECONDS);
                return ResultUtil.success("反馈信息提交成功!", CoreConst.STATUS_VALID);
            } else {
                long expire = redisService.getExpire("message:" + ip);
                return ResultUtil.error(expire + "s内不要多次提交反馈!", CoreConst.STATUS_VALID);
            }

        } catch (Exception e) {
            log.error("反馈信息提交失败", e);
            return ResultUtil.error("获取客户数据失败", Constants.STATE_INVAILD);
        }
    }
}
